﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Resources;
using System.Xml;
using System.Xml.Linq;

using ExchangeRateService.Model;

namespace ExchangeRateService.DataAccess
{
	/// <summary>
	/// Description of CurrencyRepository.
	/// </summary>
	public class CurrencyRepository
	{
		#region Fields

		readonly List<Currency> _currencies;

		#endregion // Fields

		#region Constructor

		/// <summary>
		/// Creates a new repository of customers.
		/// </summary>
		/// <param name="customerDataFile">The relative path to an XML resource file that contains customer data.</param>
		public CurrencyRepository(string customerDataFile)
		{
			_currencies = LoadSupplement(customerDataFile);
		}

		#endregion // Constructor

		#region Public Interface

		/// <summary>
		/// Returns a shallow-copied list of all customers in the repository.
		/// </summary>
		public List<Currency> GetCurrencySupplement()
		{
			return new List<Currency>(_currencies);
		}
		
		public Currency GetCurrencyByCode(String code)
		{
			return this._currencies.Where((c) => c.Code.ToLower() == code.Trim().ToLower()).FirstOrDefault();
		}
		
		public Currency GetCurrencybyName(String name)
		{
			return this._currencies.Where((c) => c.Name.ToLower() == name.Trim().ToLower()).FirstOrDefault();
		}
		
		public Currency[] GetCurrencies(String codes, params Char[] separators)
		{
			ArrayList resultSet = new ArrayList();
			
			String text = String.Empty;
			
			String[] array = codes.Split(separators);
			for (Int32 i = 0; i < array.Length; i++)
			{
				text = array[i];
				if (text.Length > 0)
				{
					resultSet.Add(this.GetCurrencyByCode(text));
				}
			}
			return (Currency[])resultSet.ToArray(typeof(Currency));
		}

		#endregion // Public Interface

		#region Private Helpers

		static List<Currency> LoadSupplement(String currencyDataFile)
		{
			// In a real application, the data would come from an external source,
			// but for this demo let's keep things simple and use a resource file.
			using (Stream stream = GetResourceStream(currencyDataFile))
				using (XmlReader reader = new XmlTextReader(stream))
					return (
						from element
						in XDocument.Load(reader).Element("Rates").Elements("Rate")
						select Currency.CreateCurrency(
							(String)element.Attribute("code"),
							(String)element.Attribute("name"),
							(Double)element.Attribute("ExchangeToUSD"),
							(Double)element.Attribute("ExchangeToCAD"),
							(Double)element.Attribute("ExchangeToEUR"),
							(Double)element.Attribute("ExchangeToGBP")
						)
					).ToList();
		}

		static Stream GetResourceStream(String resourceFile)
		{
			Uri uri = new Uri(resourceFile, UriKind.RelativeOrAbsolute);

			StreamResourceInfo info = Application.GetResourceStream(uri);
			if (info == null || info.Stream == null)
				throw new ApplicationException("Missing resource file: " + resourceFile);

			return info.Stream;
		}

		#endregion // Private Helpers
		
	}
}
